Skip to content

fuse: add subvol_root_ino mount option for subvolume support#192

Open
ukernel wants to merge 1 commit into
redfs-ubuntu-noble-6.8.0-58.60from
fuse-subvol-root-ino
Open

fuse: add subvol_root_ino mount option for subvolume support#192
ukernel wants to merge 1 commit into
redfs-ubuntu-noble-6.8.0-58.60from
fuse-subvol-root-ino

Conversation

@ukernel

@ukernel ukernel commented Jul 24, 2026

Copy link
Copy Markdown

Filesystems that support snapshots and subvolumes may have inodes with the same inode number across different subvolumes. When these inodes are accessed through the same FUSE mount, tools like cp(1) can incorrectly report "File X and Y are the same file" because they share the same device number (sb->s_dev).

Add a new mount option "subvol_root_ino" that specifies the inode number of snapshot/subvolume root. When set, FUSE allocates unique anonymous block device ID for inodes whose orig_ino matches this value, and all inodes under that subvolume inherit the same device ID. This gives each subvolume a distinct device number in stat(2), avoiding inode number conflicts.

The feature is implemented by:

  • Adding sub_dev to fuse_inode, to track per-subvolume device ID
  • Adding subvol_root_ino to fuse_conn
  • Extending fuse_iget and fuse_lookup_name to propagate sub_dev
  • Reporting fi->sub_dev in fuse_fillattr/fuse_getattr when set
  • Disabling NFS export_support when subvol_root_ino is enabled, since the two features are incompatible

@ukernel

ukernel commented Jul 24, 2026

Copy link
Copy Markdown
Author

the reason we don't use submount feature is that:
we want to support very large number of snapshots and linkable-datasets. Too many mounts will flood /proc/mounts and add heavy burden to VFS.

@ukernel
ukernel requested review from achhenderson and hbirth and removed request for achhenderson and hbirth July 24, 2026 09:10
@hbirth

hbirth commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

I don't think this is what we want unless someone convinces me how this works with the fallback fuse module.
This can all be done in user space.

@ukernel
ukernel force-pushed the fuse-subvol-root-ino branch from 1a24e23 to 88683ed Compare July 24, 2026 15:59
Comment thread fs/fuse/inode.c Outdated
Comment thread fs/fuse/inode.c Outdated
Comment thread fs/fuse/inode.c
if (fc->subvol_root_ino && fi->orig_ino == fc->subvol_root_ino) {
int err = get_anon_bdev(&get_fuse_inode(inode)->sub_dev);
if (err)
pr_warn("failed to alloc anon bdev\n");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we get to this error condition, i think fi->sub_dev is still unallocated, and err should be the errno. Should we return err here rather than continue with a null fi->sub_dev ?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not good to return error while inode is in NEW state.

Comment thread fs/fuse/inode.c
Comment thread fs/fuse/inode.c Outdated
fuse_init_inode(inode, attr, fc);
fi->orig_ino = attr->ino;
if (fc->subvol_root_ino && fi->orig_ino == fc->subvol_root_ino) {
int err = get_anon_bdev(&get_fuse_inode(inode)->sub_dev);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, it looks like we only set sub_dev when the state is new. but if a process were to hold a file open while another process evicts the parent, i /think/ the child stays cached with a stale sub_dev until it closes

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the sub_dev will get re-used if someone lookup its parent again. because d_splice_alias will try hard to re-use the original parent.

Filesystems that support snapshots and subvolumes may have inodes
with the same inode number across different subvolumes. When these
inodes are accessed through the same FUSE mount, tools like cp(1)
can incorrectly report "File X and Y are the same file" because
they share the same device number (sb->s_dev).

Add a new mount option "subvol_root_ino" that specifies the inode
number of snapshot/subvolume root. When set, FUSE allocates unique
anonymous block device ID for inodes whose orig_ino matches this
value, and all inodes under that subvolume inherit the same device
ID. This gives each subvolume a distinct device number in stat(2),
avoiding inode number conflicts.

The feature is implemented by:
- Adding sub_dev to fuse_inode, to track per-subvolume device ID
- Adding subvol_root_ino to fuse_conn
- Extending fuse_iget and fuse_lookup_name to propagate sub_dev
- Reporting fi->sub_dev in fuse_fillattr/fuse_getattr when set
- Disabling NFS export_support when subvol_root_ino is enabled,
  since the two features are incompatible

Signed-off-by: "Yan, Zheng" <ukernel@gmail.com>
@ukernel
ukernel force-pushed the fuse-subvol-root-ino branch from 88683ed to 7269925 Compare July 24, 2026 23:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants